{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "# __call__()方法\n",
    "该方法的功能类似于在类中重载 () 运算符，使得类实例对象可以像调用普通函数那样，以“对象名()”的形式使用。"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "调用__call__()方法 pangyazhou 34\n"
     ]
    }
   ],
   "source": [
    "class Person(object):\n",
    "    def __call__(self, name, age):\n",
    "        print('调用__call__()方法', name, age)\n",
    "\n",
    "person = Person()\n",
    "person('pangyazhou', 34)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "raw",
   "source": [
    "Python 中，凡是可以将 () 直接应用到自身并执行，都称为可调用对象。可调用对象包括自定义的函数、Python 内置函数以及本节所讲的类实例对象。\n",
    "对于可调用对象，实际上“名称()”可以理解为是“名称.__call__()”的简写"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% raw\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "调用__call__()方法 pangyazhou 33\n",
      "hello, lixiaolong 58\n",
      "hello, wangwei 29\n"
     ]
    }
   ],
   "source": [
    "person.__call__(\"pangyazhou\", 33)\n",
    "\n",
    "def say(name, age):\n",
    "    print('hello,', name, age)\n",
    "say('lixiaolong', 58)\n",
    "say.__call__('wangwei', 29)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 用 __call__() 弥补 hasattr() 函数的短板\n",
    "hasattr()函数的功能是查找类的实例对象中是否包含指定名称的属性或者方法，但该函数有一个缺陷，即它无法判断该指定的名称，到底是类属性还是类方法。\n",
    "类实例对象包含的方法，其实也属于可调用对象，但类属性却不是。"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n",
      "False\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "class Person(object):\n",
    "    def __init__(self):\n",
    "        self.name = 'pangyazhou'\n",
    "        self.age = 35\n",
    "    def say(self):\n",
    "        print('hello,', self.name)\n",
    "\n",
    "person = Person()\n",
    "print(hasattr(person, 'say'))\n",
    "print(hasattr(person, 'name'))\n",
    "if  hasattr(person, 'name'):\n",
    "    print(hasattr(person.name, '__call__'))\n",
    "if hasattr(person, 'say'):\n",
    "    print(hasattr(person.say, '__call__'))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}